﻿
/*******************************************************************************
 * 程序功能：
 * 平安力合采购的12232屏幕的试验
 * 
 ******************************************************************************/
 
#include "stm32f10x.h"
#include "delay.h"

#define LCD_CLK		GPIO_Pin_0
#define LCD_RW		GPIO_Pin_1
#define LCD_RS		GPIO_Pin_2

#define LCD_BUSY_BIT 7

#define CLK0()	GPIO_WriteBit(GPIOA,LCD_CLK,Bit_RESET);
#define CLK1()	GPIO_WriteBit(GPIOA,LCD_CLK,Bit_SET);
#define RW0()	GPIO_WriteBit(GPIOA,LCD_RW,Bit_RESET);
#define RW1()	GPIO_WriteBit(GPIOA,LCD_RW,Bit_SET);
#define CS0()	GPIO_WriteBit(GPIOA,LCD_RS,Bit_RESET);
#define CS1()	GPIO_WriteBit(GPIOA,LCD_RS,Bit_SET);

u8 lcd_read_byte()
{
    u8 i, temp1, temp2 = 0;

    for (i = 0; i < 8; i++)
    {
        temp1 = temp1 << 1;
        CLK1();
        Delay_Us(5);
        if (GPIO_ReadOutputDataBit(GPIOA, LCD_RW))
            temp1++;
        Delay_Us(5);
        CLK0();
        Delay_Us(5);
    }
    for (i = 0; i < 8; i++)
    {
        temp2 = temp2 << 1;
        CLK1();
        Delay_Us(5);
        if (GPIO_ReadOutputDataBit(GPIOA, LCD_RW))
            temp2++;
        Delay_Us(5);
        CLK0();
        Delay_Us(5);
    }
    return ((0xF0 & temp1) + (0x0F & temp2));
}

void lcd_write_byte(u8 data)
{
    u8 i;
    for (i = 0; i < 8; i++)
    {
        CLK1();
        if (data & 0x80)
        {
            RW1();
        }
        else
        {
            RW0();
        }
        CLK0();
        data = data << 1;
    }
}

void lcd_check_busy()
{
    Delay_Us(510);
    do
    {
        lcd_write_byte(0xFC); //11111,RW(1),RS(0),0
        Delay_Us(50);
    }
    while (0x80 & lcd_read_byte()); //BF(.7)=1 Busy
}

void lcd_write_data(u8 data)
{
    CS1();
    lcd_check_busy();
    lcd_write_byte(0xFA); //11111-RW(0)-RS(1)-0
		lcd_write_byte(0xF0 & data); //高4位
		lcd_write_byte(0xF0 & data << 4); //低4位
    CS0();
}

void lcd_write_command(u8 command)
{
    CS1();
    lcd_check_busy();
    lcd_write_byte(0xF8); //11111-RW(0)-RS(0)-0
		lcd_write_byte(0xF0 & command); //高4位
		lcd_write_byte(0xF0 & command << 4); //低4位
    CS0();
}

void lcd_clear()
{
    lcd_write_command(0x01);
    Delay_Us(10);
}

void lcd_initialize()
{
    GPIO_InitTypeDef def;

    def.GPIO_Pin = LCD_CLK | LCD_RW | LCD_RS;
    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &def);

    Delay_Ms(50);

    CS1();
    lcd_write_byte(0x30);
    CS0();
    Delay_Us(150);
    CS1();
    lcd_write_byte(0x30);
    CS0();
    Delay_Us(150);
    CS1();
    lcd_write_byte(0x30);
    CS0();
    Delay_Us(150);
    CS1();
    lcd_write_byte(0x0F);
    CS0();
    Delay_Us(150);
    CS1();
    lcd_write_byte(0x3C);
    CS0();
    Delay_Us(150);

    lcd_write_command(0x38);
    Delay_Us(5);
	lcd_write_command(0x02);//清DDRAM
	Delay_Us(5);
	lcd_write_command(0x0C);//整体显示开，游标关，反白关	
	Delay_Us(5);
	lcd_write_command(0x01);//设定DDRAM的地址计数器(AC)到"00H",并且将游标移到开头原点位置; 
	Delay_Us(5);
	lcd_write_command(0x80);//设定首次显示位置	
    Delay_Ms(1);
}

void lcd_display_chars(u8 row, u8 col, char *puts)
{
    lcd_write_command((0x80 + 16 * row) | col);
    while (*puts != '\0')
    {
        lcd_write_data(*puts);
        puts++;
    }
    lcd_write_command(0x30);
}

void lcd_display_cn_chars(u8 row, u8 col, char *puts)
{
    lcd_write_command((0x80 + 16 * row) | col);
    while (*puts != '\0')
    {
        lcd_write_data(*puts); //1个汉字写两字节
        puts++;
        lcd_write_data(*puts);
        puts++;
    }
    lcd_write_command(0x30);
}

void lcd_display_dotbytes(unsigned char dotbyte, u8 isV)
{
    unsigned char i, j;
	lcd_write_command(0x36); //8位，扩充指令开，绘图开
	for (i = 0; i < 32; i++)
	{
		lcd_write_command(0x80 | i);// 行位置
		lcd_write_command(0x80);// 列位置
		for (j = 0; j < 16; j++) //15列
		{
			lcd_write_data(dotbyte);
		}
		if (isV)
			dotbyte = ~dotbyte;
	}
	lcd_write_command(0x30);//8位，扩充指令关，绘图关
}

void lcd_drawfull()
{
    unsigned char i, j;
	lcd_write_command(0x36); //8位，扩充指令开，绘图开
	for (i = 0; i < 32; i++)
	{
		lcd_write_command(0x80 | i);// 行位置
		lcd_write_command(0x80);// 列位置
		for (j = 0; j < 16; j++) //15列
		{
			lcd_write_data(0xFF);
		}
	}
	for (i = 0; i < 32; i++)
	{
		lcd_write_command(0x80 | i);// 行位置
		lcd_write_command(0x80);// 列位置
		for (j = 0; j < 16; j++) //15列
		{
			lcd_write_data(0x00);
		}
	}
	lcd_write_command(0x30);//8位，扩充指令关，绘图关
}


void Reverse(char *arr, int begin, int end)
{
    while (begin < end)
    {
        char temp = arr[end];
        arr[end] = arr[begin];
        arr[begin] = temp;
        begin++;
        end--;
    }
}

/**
函数：u8 Float2Char(float Value,char *array)
描述：将浮点数的各个位的数值转换成字符串，通过串口发送至上位机显示
参数：float Value为欲转换的正数浮点数值，转换结果保存在字符数组*array里
**/
u8 Float2Char(float value, char *array)
{
    u8 integerPart;
    float decimalPart;
    u8 i;

    array[0] = ':';
    i = 1;

    if (value >= 1)
    {
        integerPart = (u8)value;
        decimalPart = value - integerPart;
    }
    else
    {
        integerPart = 0;
        decimalPart = value - integerPart;
    }

    if (integerPart == 0)
    {
        array[1] = '0';
        array[2] = '.';
        i = 2;
    }
    else
    {
        while (integerPart > 0)
        {
            array[i] = integerPart % 10 + '0';
            integerPart /= 10;
            i++;
        }
        Reverse(array, 1, i - 1);
        array[i] = '.';
    }

    //convert the Decimalpart
    i++;
    array[i++] = (u32)(decimalPart * 10) % 10 + '0';
    array[i++] = (u32)(decimalPart * 100) % 10 + '0';
    array[i++] = (u32)(decimalPart * 1000) % 10 + '0';
    array[i++] = (u32)(decimalPart * 10000) % 10 + '0';
    array[i++] = (u32)(decimalPart * 100000) % 10 + '0';
    array[i] = '\0';

    return i;
}

int main(void)
{
    int i;
    float j;
    char view[10];

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    lcd_initialize();
    lcd_clear();

    Delay_Ms(5);
    lcd_drawfull();
    Delay_Ms(200);

    while (1)
    {
        lcd_clear();
        
        lcd_display_cn_chars(0, 0, ">>中文显示测试");
        lcd_display_cn_chars(1, 0, "一六年四月四日");
        Delay_Ms(5000);

        lcd_clear();
        lcd_display_chars(0, 0, "ABCDEFGHYXKLMNQ");
        lcd_display_chars(1, 0, "123456789012345");
        Delay_Ms(3000);


        lcd_clear();

        lcd_display_dotbytes(0x55, 1);
        Delay_Ms(1200);

        lcd_clear();
        lcd_display_chars(0, 0, "VOLT:        v");
        lcd_display_chars(1, 0, "CURR:        mA");
        Delay_Ms(300);

        for (i = 0; i < 1300000; i += 54321)
        {
            j = i * 0.00001;
            Float2Char(j, view);
            lcd_display_chars(0, 2, (char *)view);
            lcd_display_chars(1, 2, (char *)view);
            Delay_Ms(100);
        }
        Delay_Ms(5000);
    }
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif
